﻿namespace PropOnline.Stores
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using PropOnline.Models;
    using PropOnline.Stores.Data;
    using PropOnline.ViewModels.Propiedad;

    public class PropiedadStore
    {
        public PropiedadDetallesViewModel GetDetallesPropiedad(int propiedadId)
        {
            var query =
                Database
                    .StoredProcedure("propiedad_detalle")
                    .WithParameter("PropiedadId", propiedadId);

            return query.Results(propiedad =>
                new PropiedadDetallesViewModel
                {
                    Id = propiedad.Id,
                    Calle = propiedad.CalleNombre,
                    Zona = propiedad.CalleZonaNombre,
                    Altura = propiedad.Altura,
                    Barrio = propiedad.BarrioNombre,
                    Ambientes = propiedad.Ambientes,
                    Departamento = propiedad.Departamento,
                    Piso = propiedad.Piso,
                    Moneda = (Moneda)propiedad.Moneda,
                    Precio = propiedad.Precio,
                    Telefono = propiedad.Telefono,
                    Operacion = (Operacion)propiedad.Operacion,
                    Inmobiliaria = propiedad.InmobiliariaNombre,
                    FechaPrimeraPub = (DateTime)propiedad.FechaPrimeraPub,                    
                    Superficie = propiedad.Superficie,
                    Interseccion = propiedad.InterseccionCalleNombre,
                    Dependencia = Convert.ToBoolean(propiedad.Dependencia),
                    ImagenUrl = propiedad.ImagenUrl,
                    TipoPropiedad = (TipoPropiedad)propiedad.TipoPropiedad,
                    Latitud = propiedad.Latitud != null ? Convert.ToString(propiedad.Latitud, CultureInfo.InvariantCulture) : string.Empty,
                    Longitud = propiedad.Longitud != null ? Convert.ToString(propiedad.Longitud, CultureInfo.InvariantCulture) : string.Empty,                                        
                    Caracteristicas = new List<CaracteristicaPropiedad>(),
                    UltimoAviso = new AvisoDetallesViewModel()
                    {                        
                        Fuente = (Fuente)propiedad.UltimoAvisoFuente,                        
                        Fecha = propiedad.UltimoAvisoFecha,
                        Texto = propiedad.UltimoAvisoTexto,                                                                        
                    }                    
                }).SingleOrDefault();
        }

        public IEnumerable<AvisoHistoriaViewModel> BuscarHistoria(int propiedadId)
        {
            var query =
                Database
                    .StoredProcedure("propiedad_historia")
                    .WithParameter("PropiedadId", propiedadId);

            return query.Results(aviso =>
                new AvisoHistoriaViewModel
                {                    
                    Fecha = aviso.Fecha,
                    Moneda = (Moneda)aviso.Moneda,
                    Precio = aviso.Precio,
                    Telefono = aviso.Telefono,
                    Inmobiliaria = aviso.InmobiliariaNombre,
                    Texto = aviso.Texto
                });
        }

        public IEnumerable<PropiedadResultadoViewModel> BuscarTasacion(decimal latitud, decimal longitud, string calle, int altura, int? ambientes, bool dependencia, int? superficie, TipoPropiedad? tipoPropiedad, int zonaId, Operacion? operacion)
        {
            int? filterAmbientes = null;
            if (ambientes > 0)
            {
                filterAmbientes = ambientes;
            }

            bool? filterDependencia = null;
            if (dependencia)
            {
                filterDependencia = true;
            }

            int? superficieMin = null;
            int? superficieMax = null;
            if (superficie > 0)
            {
                superficieMin = superficie - PropOnlineConstants.RangoSuperficie;
                superficieMax = superficie + PropOnlineConstants.RangoSuperficie;
            }

            sbyte? filterTipoPropiedad = null;
            if (tipoPropiedad != null && tipoPropiedad != TipoPropiedad.Todos)
            {
                filterTipoPropiedad = (sbyte)tipoPropiedad;
            }

            sbyte? filterOperacion = null;
            if (operacion != null)
            {
                filterOperacion = (sbyte)operacion;
            }

            var query = 
                Database
                    .StoredProcedure("tasacion_busqueda")
                    .WithParameter("Latitud", latitud)
                    .WithParameter("Longitud", longitud)
                    .WithParameter("NombreCalle", calle)
                    .WithParameter("Altura", altura)
                    .WithParameter("Ambientes", filterAmbientes)
                    .WithParameter("Dependencia", filterDependencia)
                    .WithParameter("SuperficieMin", superficieMin)
                    .WithParameter("SuperficieMax", superficieMax)
                    .WithParameter("TipoPropiedad", filterTipoPropiedad)
                    .WithParameter("ZonaId", zonaId)
                    .WithParameter("Operacion", filterOperacion);

            return query.Results(ToPropiedadResultadoViewModel);
        }

        public IEnumerable<PropiedadResultadoViewModel> BuscarDueñosPorCalle(string calle, int? alturaMin, int? alturaMax, IEnumerable<int> ambientes, int? mesesEnMercado, int? precioMin, int? precioMax, Moneda? moneda, int? superficie, TipoPropiedad? tipoPropiedad, int? zonaId, Operacion? operacion, int skip)
        {
            return this.BuscarPorCalle(calle, alturaMin, alturaMax, ambientes, mesesEnMercado, precioMin, precioMax, moneda, superficie, tipoPropiedad, zonaId, operacion, 1, null, skip);
        }

        public IEnumerable<PropiedadResultadoViewModel> BuscarPorCalle(string calle, int? alturaMin, int? alturaMax, IEnumerable<int> ambientes, int? mesesEnMercado, int? precioMin, int? precioMax, Moneda? moneda, int? superficie, TipoPropiedad? tipoPropiedad, int? zonaId, Operacion? operacion, int? inmobiliariaId, string inmobiliariaNombre, int skip)
        {
            DateTime? filterFechaDesde = null;
            DateTime? filterFechaHasta = null;
            if (mesesEnMercado > 0)
            {
                int meses = mesesEnMercado.Value;
                DateTime fechaMesesEnMercado = mesesEnMercado > PropOnlineConstants.MaxMesesEnMercadoInFilter ? DateTime.Today.AddMonths(-PropOnlineConstants.MaxMesesEnMercadoInFilter) : DateTime.Today.AddMonths(-meses);
                if (mesesEnMercado <= PropOnlineConstants.MaxMesesEnMercadoInFilter)
                {
                    filterFechaDesde = fechaMesesEnMercado;
                }
                else
                {
                    filterFechaHasta = fechaMesesEnMercado;
                }
            }

            int? filterPrecioMin = null;
            if (precioMin > 0)
            {
                filterPrecioMin = precioMin;
            }

            int? filterPrecioMax = null;
            if (precioMax > 0)
            {
                filterPrecioMax = precioMax;
            }

            sbyte? filterMoneda = null;
            if (moneda != null && moneda != Moneda.NoEspecifica)
            {
                filterMoneda = (sbyte)moneda;
            }

            int? superficieHasta = null;
            if (superficie > 0)
            {
                superficieHasta = superficie;
            }

            sbyte? filterTipoPropiedad = null;
            if (tipoPropiedad != null && tipoPropiedad != TipoPropiedad.Todos)
            {
                filterTipoPropiedad = (sbyte)tipoPropiedad;
            }

            sbyte? filterOperacion = null;
            if (operacion != null)
            {
                filterOperacion = (sbyte)operacion;
            }

            string filterAmbientes = null;
            if (ambientes != null && ambientes.Count() > 0)
            {
                filterAmbientes = string.Join(",", ambientes);
            }

            inmobiliariaNombre = string.IsNullOrWhiteSpace(inmobiliariaNombre) ? null : inmobiliariaNombre;

            var query =
                Database
                    .StoredProcedure("propiedad_por_calle")
                    .WithParameter("NombreCalle", calle)
                    .WithParameter("AlturaMin", alturaMin)
                    .WithParameter("AlturaMax", alturaMax)
                    .WithParameter("FechaDesde", filterFechaDesde)
                    .WithParameter("FechaHasta", filterFechaHasta)
                    .WithParameter("PrecioMin", filterPrecioMin)
                    .WithParameter("PrecioMax", filterPrecioMax)
                    .WithParameter("Moneda", filterMoneda)
                    .WithParameter("SuperficieHasta", superficieHasta)
                    .WithParameter("TipoPropiedad", filterTipoPropiedad)
                    .WithParameter("ZonaId", zonaId)
                    .WithParameter("Operacion", filterOperacion)
                    .WithParameter("AmbientesList", filterAmbientes)
                    .WithParameter("InmobiliariaId", inmobiliariaId)
                    .WithParameter("InmobiliariaNombre", inmobiliariaNombre);
                    //.WithParameter("Skip", skip)
                    //.WithParameter("Take", PropOnlineConstants.DefaultPageSize)

            return query.Results(ToPropiedadResultadoViewModel);
        }

        public IEnumerable<PropiedadResultadoViewModel> BuscarDueñosPorBarrios(IEnumerable<int> barriosId, IEnumerable<int> ambientes, int? mesesEnMercado, int? precioMin, int? precioMax, Moneda? moneda, int? superficie, TipoPropiedad? tipoPropiedad, int? zonaId, Operacion? operacion, int skip)
        {
            return this.BuscarPorBarrios(barriosId, ambientes, mesesEnMercado, precioMin, precioMax, moneda, superficie, tipoPropiedad, zonaId, operacion, 1, null, skip);
        }

        public IEnumerable<PropiedadResultadoViewModel> BuscarPorBarrios(IEnumerable<int> barriosId, IEnumerable<int> ambientes, int? mesesEnMercado, int? precioMin, int? precioMax, Moneda? moneda, int? superficie, TipoPropiedad? tipoPropiedad, int? zonaId, Operacion? operacion, int? inmobiliariaId, string inmobiliariaNombre, int skip)
        {
            string filterBarriosId = null;
            if (barriosId != null && barriosId.Count() > 0)
            {
                filterBarriosId = string.Join(",", barriosId);
            }

            DateTime? filterFechaDesde = null;
            DateTime? filterFechaHasta = null;
            if (mesesEnMercado > 0)
            {
                int meses = mesesEnMercado.Value;
                DateTime fechaMesesEnMercado = mesesEnMercado > PropOnlineConstants.MaxMesesEnMercadoInFilter ? DateTime.Today.AddMonths(-PropOnlineConstants.MaxMesesEnMercadoInFilter) : DateTime.Today.AddMonths(-meses);
                if (mesesEnMercado <= PropOnlineConstants.MaxMesesEnMercadoInFilter)
                {
                    filterFechaDesde = fechaMesesEnMercado;
                }
                else
                {
                    filterFechaHasta = fechaMesesEnMercado;
                }
            }

            int? filterPrecioMin = null;
            if (precioMin > 0)
            {
                filterPrecioMin = precioMin;
            }

            int? filterPrecioMax = null;
            if (precioMax > 0)
            {
                filterPrecioMax = precioMax;
            }

            sbyte? filterMoneda = null;
            if (moneda != null && moneda != Moneda.NoEspecifica)
            {
                filterMoneda = (sbyte)moneda;
            }

            int? superficieHasta = null;
            if (superficie > 0)
            {
                superficieHasta = superficie;
            }

            sbyte? filterTipoPropiedad = null;
            if (tipoPropiedad != null && tipoPropiedad != TipoPropiedad.Todos)
            {
                filterTipoPropiedad = (sbyte)tipoPropiedad;
            }

            sbyte? filterOperacion = null;
            if (operacion != null)
            {
                filterOperacion = (sbyte)operacion;
            }

            string filterAmbientes = null;
            if (ambientes != null && ambientes.Count() > 0)
            {
                filterAmbientes = string.Join(",", ambientes);
            }

            inmobiliariaNombre = string.IsNullOrWhiteSpace(inmobiliariaNombre) ? null : inmobiliariaNombre;

            var query =
                Database
                    .StoredProcedure("propiedad_por_barrios")
                    .WithParameter("BarriosIdList", filterBarriosId)
                    .WithParameter("FechaDesde", filterFechaDesde)
                    .WithParameter("FechaHasta", filterFechaHasta)
                    .WithParameter("PrecioMin", filterPrecioMin)
                    .WithParameter("PrecioMax", filterPrecioMax)
                    .WithParameter("Moneda", filterMoneda)
                    .WithParameter("SuperficieHasta", superficieHasta)
                    .WithParameter("TipoPropiedad", filterTipoPropiedad)
                    .WithParameter("ZonaId", zonaId)
                    .WithParameter("Operacion", filterOperacion)
                    .WithParameter("AmbientesList", filterAmbientes)
                    .WithParameter("InmobiliariaId", inmobiliariaId)
                    .WithParameter("InmobiliariaNombre", inmobiliariaNombre);
                    //.WithParameter("Skip", skip)
                    //.WithParameter("Take", PropOnlineConstants.DefaultPageSize)

            return query.Results(ToPropiedadResultadoViewModel);
        }        
        
        private static PropiedadResultadoViewModel ToPropiedadResultadoViewModel(dynamic propiedad)
        {
            if (propiedad == null)
            {
                return null;
            }

            return new PropiedadResultadoViewModel
            {
                Id = propiedad.Id,
                Calle = propiedad.CalleNombre,
                Interseccion = propiedad.InterseccionCalleNombre,
                Zona = propiedad.CalleZonaNombre,
                Altura = propiedad.Altura,
                Barrio = propiedad.BarrioNombre,
                Ambientes = propiedad.Ambientes,
                Departamento = propiedad.Departamento,
                Piso = propiedad.Piso,
                Moneda = (Moneda)propiedad.Moneda,
                Precio = propiedad.Precio,
                FechaPrimeraPub = (DateTime)propiedad.FechaPrimeraPub,
                Inmobiliaria = propiedad.InmobiliariaNombre,
                Dependencia = Convert.ToBoolean(propiedad.Dependencia),               
                ImagenUrl = propiedad.ImagenUrl,
                Telefono = propiedad.Telefono,
                FechaUltimaPublicacion = propiedad.UltimoAvisoFecha,
                Fuente = (Fuente)propiedad.UltimoAvisoFuente,
                TipoPropiedad = (TipoPropiedad)propiedad.TipoPropiedad,
                Superficie = propiedad.Superficie
            };
        }
    } 
}